home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 1/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
-
- // A graphics library demonstrating the simplicity of fast
- // graphics in 320x200x256-color VGA mode. The code is not
- // fully optimized but it is pretty close; an extra 5% or so
- // might be squeezed out of the putimage() for example. Be
- // careful when altering pseuodoregisters; while doing one
- // load the compiler may trash another register which was just
- // loaded with something pertinent.
-
-
- // Functions provided include point, row, and array (image)
- // drawing functions, as well as palette functions using BIOS
- // and line-drawing and circle-drawing functions.
-
- // Main() demonstrates most of the functions in a pretty and
- // interesting way.
-
-
- void GrInit(void);
- void GrClose(void);
- unsigned char GetPixel(unsigned int x, unsigned int y);
- void PutPixel(unsigned int x, unsigned int y, unsigned char
- color);
- void FillRow(unsigned x, unsigned y, unsigned char color,
- unsigned length);
- void PutRow(unsigned x, unsigned y, char *data, unsigned length);
- void GetRow(unsigned x, unsigned y, char *data, unsigned length);
- void PutImage(unsigned x, unsigned y, char *data, unsigned rows,
- unsigned cols);
- void GetImage(unsigned x, unsigned y, char *data, unsigned rows,
- unsigned cols);
- void GetAllPalette(char (*palette)[3]);
- void SetAllPalette( char (*palette)[3]);
- void Circle(int x, int y, int radius, unsigned char color);
- void Line(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
- unsigned char color);
-
-
-
- #define VIDEOINT 0x10
-
- #pragma inline
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 2/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- // 'dos.h' is essential
- #include <dos.h>
- // we need 'math.h' for sqrt() in Circle() and abs() in Line()
- #include <math.h>
- // we need 'conio.h' for getch()
- #include <conio.h>
-
- int rowOffset[200]; // as an optimization,
- // rowOffset will be used as a table to
- // avoid the multiplication column+(320*row)
- // when getting the actual memory address of
- // a pixel or a row
-
-
-
- // GrInit() initializes the rowOffset table and switches video
- // modes to 320x200 with 256 colors
- void GrInit()
- {
- int i;
- // Pre-setup our multipications for column,
- //row -> screen address
- for (i=0; i<200; ++i)
- {
- rowOffset[i]=i*320;
- }
- // Set video mode to 320x200 --
- // sophisticated users may wish to research checking
- // for the availability of VGA/MCGA prior to switching
- // modes.
-
- _AH=0;
- _AL=0x13;
- geninterrupt(VIDEOINT);
- }
-
-
-
- // GrClose sets the video back into text mode
- void GrClose()
- {
- // set video mode 80x25 color text -- we're assuming
- // that that's available
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 3/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- // if we're using VGA
- _AH=0;
- _AL=0x3;
- geninterrupt(VIDEOINT);
- }
-
-
-
- // GetPixel returns the pixel value at a given (x,y) screen
- // location
- unsigned char GetPixel(unsigned int x, unsigned int y)
- {
- return *((char far *) 0xA0000000L+ (x+rowOffset[y]));
- }
-
-
-
- // PutPixel changes the pixel at a given (x,y) screen location
- // to value 'color'
- void PutPixel( unsigned int x, unsigned int y,
- unsigned char color)
- {
- *((char far *) 0xA0000000L + (x+rowOffset[y]))=color;
- }
-
-
-
- // FillRow writes a row of 'color' color pixels of length
- // 'length' starting at screen location (x,y).
- void FillRow( unsigned x, unsigned y, unsigned char color,
- unsigned length )
- {
- _ES=0xA000; // The segment for screen memory
- _DI=x+rowOffset[y]; // The offset in screen to write at
- _CX=length; // Number of bytes for rep stosb
- _AL=color; // The value stosb will store in video
- // memory
- asm {
- cld // set direction flag so DI
- // will increment
- rep stosb // zap a row of color AL out to
- // video memory al->[es:di]
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 4/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- }
-
-
-
- // PutRow transfers a row of pixels from 'data' to screen
- // starting at (x,y) and continuing for 'length'. A rep
- // movsw instead of rep movsb might optimize this slightly for
- // even-length rows
- void PutRow(unsigned x, unsigned y, char *data, unsigned length)
- {
- // You may remove all lines marked with '***' if 'data' is a
- // near pointer (i.e. if 'data' was not allocated from the far
- // heap and was not declared as 'far' data.) Remove them all
- // if you remove any.
-
- _ES=0xA000;
- _DI=x+rowOffset[y]; // the offset in video memory for
- // the row start
- _SI=FP_OFF(data);
- // load AX last since many C
- // instructions will trash AX
- _AX=FP_SEG(data); // store data's segment in AX for
- // now ***
- asm {
- push ds // Save DS since we're going to
- // alter it ***
- mov ds,ax // load register from AX (loaded
- // above) ***
- mov cx,length // we're moving 'length' bytes
- // total
- cld // clear the direction flag to
- // increment si and di
- rep movsb // dump the whole row out to video
- // memory [ds:si]->[es:di]
- pop ds // Restore DS ***
- }
- }
-
-
-
- // GetRow() copies a row of pixels of length 'length' out of
- // video memory into the buffer at 'data'. rep movsw might be
- // slightly faster here also.
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 5/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- void GetRow(unsigned x, unsigned y, char *data, unsigned length)
- {
- _SI=x+rowOffset[y]; // the offset in video memory for
- // the row start
- _ES=FP_SEG(data); // set up ES:DI to point to data
- _DI=FP_OFF(data);
- _AX=0xA000; // load video segment in AX
- asm {
- push ds // save DS since we have to use DS
- // for copying
- mov ds,ax // load DS with segment for video
- // memory from AX (0xA000)
- mov cx,length // we're moving 'length' bytes
- // total
- cld // clear the direction flag to
- // increment si and di
- rep movsb // get the whole row from video
- // memory [ds:si]->[es:di]
- pop ds // Restore DS
- }
- }
-
-
-
- // GetImage() uses repeated GetRow's to store a screen image
- // in buffer at 'data'
- void GetImage( unsigned x, unsigned y, char *data, unsigned
- columns, unsigned rows)
- {
- int i;
- for (i=0; i<rows; ++i)
- {
- GetRow(x,y+i,data,columns);
- data+=columns;
- }
- }
-
-
-
- // PutImage() uses repeated PutRow's to display a screen image
- // from 'data' buffer
- void PutImage( unsigned x, unsigned y, char *data,
- unsigned columns, unsigned rows)
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 6/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- {
- int i;
- for (i=0; i<rows; ++i)
- {
- PutRow(x,y+i,data,columns);
- data+=columns;
- }
- }
-
-
-
- // traceWait() loops doing in-ports from port 0x3DA until bit 3
- // of the value read changes from 1 to 0, meaning a vertical
- // retrace just started.
- void traceWait()
- {
- retracewait1:
- asm {
- mov dx,0x3DA
- in al,dx
- and al,8
- jnz retracewait1
- }
- retracewait2:
- asm {
- mov dx,0x3DA
- in al,dx
- and al,8
- jz retracewait2
- }
- }
-
-
-
- // SetAllColors: sets the whole range of palette registers
- // from an array containing R,G,B values
- void SetAllColors(char (*palette)[3])
- {
- int paletteSegment,paletteOffset;
- traceWait(); // if we change the palette
- // while the screen is being
- // drawn, parts will appear in the
- // old colors and parts in the new
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 7/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- // and this will look odd. So wait
- // for vert. retrace!
- _ES=FP_SEG(palette); // load ES:DX with palette's
- // address
- _DX=FP_OFF(palette);
- _AX=0x1012; // service 0x10 subservice 0x12
- _BX=0; // starting register
- _CX=256; // number of registers (256 = all)
- geninterrupt(VIDEOINT);
- }
-
-
-
- void GetAllColors(char (*palette)[3])
- {
- _ES=FP_SEG(palette); // load ES:DX with palette's
- // address
- _DX=FP_OFF(palette);
- _AX=0x1017; // service 0x10 subservice 0x17
- _BX=0; // starting register
- _CX=256; // number of registers (256 = all)
- geninterrupt(VIDEOINT);
- }
-
-
-
- // Line takes starting and ending coordinates and a color, and
- // draws a line using Bresenham's line drawing algorithm. The
- // algorithm uses long ints like ints that also have 16 bits of
- // precision after the decimal point.
- // Bresenham's assigns an increment of +/- 1.0 to whatever
- // variable X or Y has the greater difference and assigns some
- // increment smaller than 1 to the axis with a smaller
- // differential. Then the line is drawing by successively
- // incrementing X and Y from the start until the end is
- // reached, and rounding each value to the nearest pixel.
- void Line(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
- unsigned char color)
- {
- long xDiff,yDiff,xInc,yInc,x,y;
- int screenX,screenY;
- xDiff=((long) abs(x1-x2)) << 16;
- yDiff=((long) abs(y1-y2)) << 16;
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 8/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- if (xDiff>yDiff)
- {
- xInc=1L<<16; yInc=yDiff/(xDiff>>16);
- }
- else
- {
- xInc=xDiff/(yDiff>>16); yInc=1L<<16;
- }
- if (x2 < x1) xInc= -xInc;
- if (y2 < y1) yInc= -yInc;
- x=((long) x1) << 16; y=((long) y1) << 16;
- do
- {
- screenX=(x+32767L)>>16; screenY=(y+32767L)>>16;
- PutPixel(screenX,screenY,color);
- x+=xInc; y+=yInc;
- } while (screenX!=x2 || screenY!=y2);
- PutPixel(x2,y2,color); // wrap up the line else we will be
- // stopping one pixel before the
- // end
- }
-
-
-
- // Just for fun, a slightly optimized circle drawing routine
- void Circle(int centerX, int centerY, int radius, unsigned char
- color)
- {
- int i,newY,radiusSquared,distance;
- radiusSquared=radius*radius;
- // sqrt(2)/2*radius is the horizontal or vertical portion
- // of 1/8 circle
-
- distance=sqrt(2.0)/2.0*radius;
-
- // as an optimization, we will just do 1/8 of a circle and
- // do 7 other pixels as reflections, since a circle has
- // 8-way symmetry -- all those SQRT's
- // can take time! Superfast SQRT's might be done with a
- // lookup table.
-
- for (i=0; i<=distance; ++i)
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 9/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- // the formula for a circle is x^2+y^2=radius^2
- newY=sqrt(radiusSquared-i*i);
- PutPixel(centerX+i, centerY+newY,color);
- PutPixel(centerX-i, centerY-newY,color);
- PutPixel(centerX+i, centerY-newY,color);
- PutPixel(centerX-i, centerY+newY,color);
- PutPixel(centerX+newY,centerY+i,color);
- PutPixel(centerX-newY,centerY-i,color);
- PutPixel(centerX+newY,centerY-i,color);
- PutPixel(centerX-newY,centerY+i,color);
- }
- }
-
-
-
- #define ROWSIZE 34
- char logo[5][ROWSIZE]=
- {
- 1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,0,
- 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,1,
- 1,1,1,0,0,1,0,0,1,0,1,1,1,0,0,1,0,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,0,1,
- 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,
- 1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,0
- };
-
-
-
- char image[2700];
-
-
-
- int main()
- {
- int i,j, k;
- char palette[256][3], tempRed, tempGreen, tempBlue;
- char *temp,color;
- GrInit();
-
- // Demonstrate Line function
- i=15;
- for (j=199; j>0; j-=10)
- {
- Line(0,j,i,0,j/10+16);
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 10/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- i += 16 ;
- }
-
- // Demonstrate FillRow function with a series of rows.
- for (i=92; i<=108; i+=2)
- {
- FillRow(136,i,7,49);
- }
-
- // Put BORLAND logo down
- PutImage(145,98,&(logo[0][0]),ROWSIZE,5);
-
- // Draw a circle around it
- Circle(160,100,25,3);
- getch(); // pause to let the user admire our
- // work!
-
- // and now some fancy stuff;
- // we will get the image and 'shade' it by incrementing the
- // color according to the column+row
- GetImage(134,74,image,52,52);
- temp=image;
- for (i=0; i<52; ++i)
- {
- for (j=0; j<52; ++j)
- {
- if (*temp!=0)
- {
- // change BORLAND to 128 higher for contrast
- if (*temp==1)
- *temp=(*temp+i+j+128)%256;
- else
- *temp=(*temp+i+j)%256;
- }
- ++temp;
- }
- }
- // put the altered image back down
- PutImage(134,74,image,52,52);
- GetAllColors(palette);
- // now we'll 'rotate' the palette by 1 forever, by copying
- // all the colors down to the next lower color, until a key
- // is hit. Palette entry 0 is not altered, otherwise the
-
-
-
-
-
-
-
-
-
-
-
-
-
- PRODUCT : Borland C++ NUMBER : 1031
- VERSION : 3.x
- OS : DOS
- DATE : October 23, 1992 PAGE : 11/11
-
- TITLE : Some Graphics primitives using 256-Color VGA Mode.
-
-
-
-
- // background for the whole screen would be flashing.
- while (!kbhit())
- {
- tempRed=palette[1][0]; tempGreen=palette[1][1];
- tempBlue=palette[1][2];
- for (j=2; j<256; ++j)
- {
- for (k=0; k<3; ++k) palette[j-1][k]=palette[j][k];
- }
- palette[255][0]=tempRed; palette[255][1]=tempGreen;
- palette[255][2]=tempBlue;
- delay(15);
- SetAllColors(palette);
- }
- GrClose();
- return(0);
- }
-
-
-
- DISCLAIMER: You have the right to use this technical information
- subject to the terms of the No-Nonsense License Statement that
- you received with the Borland product to which this information
- pertains.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-